package com.tzy.spi.aop;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AopBeanProxy<T> implements InvocationHandler {

    //<method,aspectList<aspect>>
    private HashMap<String, ArrayList<AopEnhancer.AspectHolder>> methodAspectMapping;
    private Map<String, AopInvoker> invokerCache= new ConcurrentHashMap<>();
    private  T nativeBean;


    public AopBeanProxy(HashMap<String, ArrayList<AopEnhancer.AspectHolder>> methodAspectMapping, T nativeBean) {
        this.methodAspectMapping = methodAspectMapping;
        this.nativeBean=nativeBean;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


        String methodName = method.getName();
        //没有切面直接调用
        if (!methodAspectMapping.containsKey(methodName)) {
            return method.invoke(nativeBean,args);
        }
        //构建切面拦截器链，链式调用执行
        invokerCache.computeIfAbsent(methodName,(key)->{
            ArrayList<AopEnhancer.AspectHolder> aspectHolders = methodAspectMapping.get(methodName);
            return new AopInvoker(aspectHolders, method, nativeBean);
        });

        AopInvoker aopInvoker = invokerCache.get(methodName);

        return aopInvoker.invoke(args);
    }


}
